<?php

/**
 * Classe de acesso aos resultados do calculo de frete
 *
 * @category Tavs
 * @package Tavs_Frete_Resultado
 *
 * @author Tales Santos <tales.augusto.santos>
 */
class Tavs_Frete_Resultado
{
	/**
	 * Resultado da consulta
	 *
	 * @var array
	 */
	protected $_data = array();

	/**
	 * Mapeamento dos parametros
	 *
	 * @var array
	 */
	protected $_paramsMap = array(
		'Codigo' 				=> 'codigo',
		'Valor'  				=> 'valor',
		'PrazoEntrega' 			=> 'prazoEntrega',
		'ValorMaoPropria' 		=> 'valorMaoPropria',
		'ValorAvisoRecebimento' => 'valorAvisoRecebimento',
		'ValorValorDeclarado'   => 'valorDeclarado',
		'EntregaDomiciliar' 	=> 'entregaDomiciliar',
		'EntregaSabado' 		=> 'entregaSabado',
		'Erro' 					=> 'erro',
		'MsgErro' 				=> 'msgErro'
	);

	/**
	 * Construct.
	 *
	 * @param array $data Array com o resultado vindo do site do correio
	 *
	 * @return void
	 */
	public function __construct(array $data)
	{
		$this->_normalizeParams($data);
	}

	/**
	 * Normaliza os parametros mudando seus tipos e seus nomes
	 *
	 * @param array $data Array com os parametros
	 *
	 * @return Tavs_Frete_Resultado
	 */
	protected function _normalizeParams($data)
	{
		$newParams = array();

		foreach ($data as $servico => $servicoParams)
		{
			$newServicoParams = array();
			foreach ($servicoParams as $paramName => $paramValue)
			{
				$newParamName = $this->_paramsMap[$paramName];

				$method = '_format' . ucfirst($newParamName);

				$value = $paramValue;
				if (method_exists($this, $method)) {
					$value = $this->$method($paramValue);
				}

				$newServicoParams[$newParamName] = $value;
			}

			$newParams[$servico] = $newServicoParams;
		}

		$this->_data = $newParams;

		return $this;
	}

	/**
	 * Formata o codigo do servico
	 *
	 * @param mixed $value
	 *
	 * @return int
	 */
	protected function _formatCodigo($value)
	{
		return (int)$value;
	}

	/**
	 * Formata o valor do frete
	 *
	 * @param mixed $value
	 *
	 * @return float
	 */
	protected function _formatValor($value)
	{
		$value = str_replace(',', '.', $value);
		return (float)$value;
	}

	/**
	 * Formata o prazo de entrega do frete
	 *
	 * @param mixed $value
	 *
	 * @return int
	 */
	protected function _formatPrazoEntrega($value)
	{
		return (int)$value;
	}

	/**
	 * Formata o valor do servico de mao propria
	 *
	 * @param mixed $value
	 *
	 * @return float
	 */
	protected function _formatValorMaoPropria($value)
	{
		return $this->_formatValor($value);
	}

	/**
	 * Formata o valor do servico de aviso recebimento
	 *
	 * @param mixed $value
	 *
	 * @return float
	 */
	protected function _formatValorAvisoRecebimento($value)
	{
		return $this->_formatValor($value);
	}

	/**
	 * Formata o valor declarado
	 *
	 * @param mixed $value
	 *
	 * @return float
	 */
	protected function _formatValorDeclarado($value)
	{
		return $this->_formatValor($value);
	}

	/**
	 * Formata o parametro entrega domiciliar
	 *
	 * @param mixed $value
	 *
	 * @return bool
	 */
	protected function _formatEntregaDomiciliar($value)
	{
		return (strtoupper($value) == 'S');
	}

	/**
	 * Formata o parametro entrega no sabado
	 *
	 * @param mixed $value
	 *
	 * @return bool
	 */
	protected function _formatEntregaSabado($value)
	{
		return (strtoupper($value) == 'S');
	}

	/**
	 * Formata o erro
	 *
	 * @param mixed $value
	 *
	 * @return int
	 */
	protected function _formatErro($value)
	{
		return (int) $value;
	}

	/**
	 * Retorna o servico ou um parametro do resultado do calculo
	 *
	 * @param string $name
	 *
	 * @return mixed|stdClass
	 */
	public function __get($name)
	{
		if (count($this->_data) == 1)
		{
			$obj = $this->getServico();
			return $this->_getStdClassProperty($obj, $name);
		}
		else {
			return $this->getServico((int)$name);
		}
	}

	/**
	 * Retorna o valor de uma propriedade de stdClass
	 *
	 * @param stdClass $obj
	 * @param string $property
	 *
	 * @return mixed
	 */
	protected function _getStdClassProperty(stdClass $obj, $property)
	{
		if (property_exists($obj, $property)) {
			return $obj->{$property};
		}
		else {
			throw new Tavs_Frete_Exception('parametro ' . $property . ' invalido');
		}
	}

	/**
	 * Retorna os parametros do servico.
	 *
	 * @param int $servico ID do servico
	 *
	 * @return stdClass
	 */
	public function getServico($servico = null)
	{
		if (null === $servico) {
			$objServico = reset($this->_data);
		}
		elseif (array_key_exists($servico, $this->_data)) {
			$objServico = $this->_data[$servico];
		}
		else {
			throw new Tavs_Frete_Exception('servico ' . $servico . ' nao se encontra nos resultados');
		}

		return (object)$objServico;
	}

}